Override perform_get() and perform_set() without a subclass#30
Override perform_get() and perform_set() without a subclass#30
Conversation
invoked at the daemon level.
to use for perform_get() and perform_set().
methods in one go.
…formers() is invoked.
|
Is there documentation on what constitutes a valid performer method? Some things I immediately wonder about:
Also I believe that A quick example: from typing import Callable
class Bar:
def __init__(self, name:str):
self.name = name
def core_method(self, *args):
print(f"Core method of {repr(self)} name={self.name} called with args: {args}")
class Foo:
def __init__(self, method:Callable, b:str):
self.anothers_method = method
self.b = b
def call_anothers(self, arg):
self.anothers_method(arg, self.b)
def core_method(self, *args):
print(f"Core method of {repr(self)} {self.b} called with args: {args}")
x = Bar('external')
y = Foo(x.core_method, 'bval, foo instance')
y.call_anothers('some arg to call_anothers')
y.core_method('some arg to y core method')and a deep dive is here https://docs.python.org/3/howto/descriptor.html |
|
@baileyji The main thing I'm trying to accomplish with the wrapper method is to allow the implementation to define/provide a performer method that doesn't receive an Item instance as the first argument. If I used something like types.MethodType to replace the Item.perform_set reference, whatever I used there would receive 'self' (the mktl.Item instance) as the first argument. I believe your example code effectively does the same thing as what's in the pull request; I store a reference to the externally provided method, regardless of whether it is a function or an instance method, and replace Item.perform_set with Item._perform_set_wrapper so the rest of the handling chain remains unaware. I'll add language to the docstrings about the expected return values, I see that's missing. Thanks for the heads-up. With respect to how the request is executed, I will add language to the docstrings for Item.perform_get() and Item.perform_set(), since it's relevant there as well-- and the documentation for the other methods should all be landing in the same place so it's only described once. I can flesh out a similar structure for handling the raw request, in addition to this mechanism for overriding perform_get() and perform_set(); I'll look into that. |
…s(), but for full requests.
with a daemon, so add_handlers() doesn't need to start with the full key.
down in the Item class for performers.
as broken out in the Item class.
|
This pull request is starting to get a bit wordy with the families of methods to handle the various ways of adding and setting requests, but I think it's reasonably complete at this point. |
|
@klanclos I see that from the code. The example code I gave and the link demonstrates why that is, if I'm reading correctly, superfluous. Item appears to have a public .perform_set method that a subclass is expected to implement, an self._perform_set_wrapper calls the callable stored at Replacing class Bar:
def __init__(self, name:str):
self.name = name
def core_method(self, *args):
print(f"Core method of {repr(self)} name={self.name} called with args: {args}")
def set_caller(self, arg):
self.core_method=arg
x= Bar('bar')
print('Calling core method')
x.core_method()
print(f'Vars of {repr(x)}: {vars(x)}')
x.set_caller(lambda *args, **kwargs: print('lambda', args, kwargs, type(x).core_method(x, "a very perverse call")))
print(f'Vars of {repr(x)}: {vars(x)}')
print('Calling core method')
x.core_method()gets So strictly speaking the wrappers are just obfuscating. I'd go further though. I'd argue that in this instance a subclass should not override perform_set at all. The base class should implement perform_set with all needed checks. and stub out Also setting a performer can be assignment to _perform_set directly and the parent now has direct visibility on potential conflicts there wehn |
This PR not ready for review. The discussion still underway.
This pull requests enables the developer to specify how GET and SET requests will be handled on a per-item basis without requiring the use of custom subclasses of mktl.Item.